package scenic.study.net;


import com.nova.scenic.projectlibs.util.debug.RegexExpressUtil;
import com.nova.scenic.projectlibs.util.io.StreamUtil;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SimpleNetwork {

    private static final String TAG = "SimpleNetwork";



    private String url = null;
    private URLConnection connection;
    private InputStream inputStream;
    private OutputStream outputStream;

    public SimpleNetwork(String url) {
        this.url = url;
    }


    private ResultError errorCode;


    public enum ResultError {

        ERROR_CODE_SERVER("无法连接到服务器"),
        SUCCESS("成功"),
        ERROR_CODE_MALFORMED_URL("URL格式不正确"), URLConnectionNullPoint("无法建立连接");

        ResultError(String describe) {
            this.describe = describe;
        }

        String describe;

        @Override
        public String toString() {
            return super.toString() + ":" + describe;
        }
    }

    public ResultError error() {
        return errorCode;
    }

    private void errorSet(ResultError errorCode) {
        this.errorCode = errorCode;
    }

    public int code() {
        try {
            connect();
        } catch (URLConnectionNullPointException e) {
            e.printStackTrace();
            return -1;
        }
        int code = -1;
        try {
            Map<String, List<String>> fields = getConnection().getHeaderFields();
            Collection<List<String>> values = fields.values();
            Iterator<List<String>> iterator = values.iterator();
            Pattern pattern = Pattern.compile(".+HTTP/.+(\\d{3}).+");
            while (iterator.hasNext()) {
                List<String> value = iterator.next();
                Matcher matcher = pattern.matcher(value.toString());
                if (matcher.matches()) {
                    String codeString = matcher.group(1);
                    return Integer.parseInt(codeString);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            //{null=[HTTP/1.1 200 OK], Content-Length=[0], Content-Type=[text/html;charset=UTF-8], Date=[Tue, 21 Jun 2016 02:11:44 GMT], Server=[Apache-Coyote/1.1], X-Android-Received-Millis=[1466475100909], X-Android-Response-Source=[NETWORK 200], X-Android-Selected-Transport=[http/1.1], X-Android-Sent-Millis=[1466475100894]}
        }

        if (code == -1) {
            System.err.println("get code error  " + getConnection().getHeaderFields() + " error " + error() + "  " + error().describe + "  " + error().ordinal());
        }

        return code;
    }

    public SimpleNetwork header(Map<String, String> header) {
        Iterator<Map.Entry<String, String>> iterator = header.entrySet().iterator();
        try {
            connect();
        } catch (URLConnectionNullPointException e) {
            e.printStackTrace();
        }
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            getConnection().setRequestProperty(entry.getKey(), entry.getValue());
        }
        return this;
    }

    public SimpleNetwork connect() throws URLConnectionNullPointException {
        if (connection == null) {
            URL url;
            try {
                url = new URL(this.url);
            } catch (MalformedURLException e) {
                e.printStackTrace();
                errorSet(ResultError.ERROR_CODE_MALFORMED_URL);
                return this;
            }

            try {
                connection = url.openConnection();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (connection == null) {
            errorSet(ResultError.URLConnectionNullPoint);
            throw new URLConnectionNullPointException();
        }

        return this;
    }

    public InputStream inputStream() {

        if (inputStream != null) {
            return inputStream;
        }

        try {
            connect();
        } catch (URLConnectionNullPointException e) {
            e.printStackTrace();
            return null;
        }
        try {
            inputStream = getConnection().getInputStream();
        } catch (IOException e) {
            e.printStackTrace();
            errorSet(ResultError.ERROR_CODE_SERVER);
        }

        return inputStream;
    }

    public OutputStream outputStream() {
        if (outputStream != null) {
            return outputStream;
        }

        try {
            connect();
        } catch (URLConnectionNullPointException e) {
            e.printStackTrace();
            return null;
        }
        getConnection().setDoOutput(true);
        try {
            outputStream = getConnection().getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
            errorSet(ResultError.ERROR_CODE_SERVER);
        }
        return outputStream;
    }

    public URLConnection getConnection() {
        return connection;
    }

    public String string() throws MayNeedAlertErrorException {
        if (inputStream() == null) {
            throw new MayNeedAlertErrorException();
        }
        return StreamUtil.streamToString(inputStream(), null);
    }

    public SimpleNetwork post(Map<String, String> body) throws MayNeedAlertErrorException {
        try {
            Set<Map.Entry<String, String>> entrySets = body.entrySet();
            StringBuffer stringBuffer = new StringBuffer();

            int index = 0;
            for (Map.Entry<String, String> entry : entrySets) {
                String key = entry.getKey();
                String value = URLEncoder.encode(entry.getValue(), "utf-8");
                if(index > 0){
                    stringBuffer.append("&");
                }
                stringBuffer
                        .append(key)
                        .append("=")
                        .append(value)

                ;
                index++;
            }

            post(stringBuffer.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
        return this;
    }

    public SimpleNetwork post(String jsonString) throws MayNeedAlertErrorException {

        System.out.println(jsonString);
        if (outputStream() == null) {
            throw new MayNeedAlertErrorException();
        }
        DataOutputStream outputStream = new DataOutputStream(outputStream());
//        OutputStreamWriter writer = new OutputStreamWriter(outputStream());
        //write parameters
        try {
            outputStream.write(jsonString.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            outputStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return this;
    }

    public static class URLConnectionNullPointException extends Exception {

    }

    public static class MayNeedAlertErrorException extends Exception {

    }


    public static boolean validateDataFormat(String s) {
        if (null == s)
            return false;

        try {
            //TODO(liuzd) 优化 这里标准的SDK无法访问到,需要以后反射处理
//			android.net.SimpleNetwork.numericToInetAddress(s);
        } catch (IllegalArgumentException e) {
            return false;
        }

        Pattern pattern = Pattern
                .compile(RegexExpressUtil.CHECK_IP);

        Matcher matcher = pattern.matcher(s);

        return matcher.matches();
    }



    public static final int CONNECTION_TYPE_WIFI = 0;
    public static final int CONNECTION_TYPE_CM_NET = 1;
    public static final int CONNECTION_TYPE_WAP = 2;
    public static final int CONNECTION_TYPE_NO_CONNECT = 3;
}
